package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.article.domain.StrategyDetail;
import cn.wolfcode.luowowo.article.service.IStrategyDetailService;
import cn.wolfcode.luowowo.search.domain.DestinationTemplate;
import cn.wolfcode.luowowo.search.domain.StrategyTemplate;
import cn.wolfcode.luowowo.search.query.StrategySearchQuery;
import cn.wolfcode.luowowo.search.repository.IDestinationEsRepository;
import cn.wolfcode.luowowo.search.repository.IStrategyEsRepository;
import cn.wolfcode.luowowo.search.service.IDestinationEsService;
import cn.wolfcode.luowowo.search.service.IStrategyEsService;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.InternalAggregation;
import org.elasticsearch.search.aggregations.InternalMultiBucketAggregation;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategyEsServiceImpl implements IStrategyEsService {
    @Autowired
    private IStrategyEsRepository repository;
    @Reference
    private IStrategyDetailService strategyDetailService;

    @Override
    public List<Map<String, Object>> queryThemeCommend() {
        List<Map<String, Object>> data = new ArrayList<>();
        List<StatisVO> list = this.getStatsVoList("themeId", "themeName", "themeGroup");

        //优化2 取集合前十个
        if(list.size()>10){
            list = list.subList(0,10);
        }

        //通过themeId查询目的地集合
        Map<String,Object> map = null;
        for (StatisVO vo : list) {
            map = new HashMap<>();
            //主题
            map.put("theme",vo);
            //某一个主题下关联的目的地集合
            List<StatisVO> dests  = this.getDestByThemeId(vo.getId());
            map.put("dests",dests);
            data.add(map);
        }

        //通过上边查出来的数据组装成完整数据,并返回
        return data;
    }

    private List<StatisVO> getStatsVoList(String idField,String nameField,String groupName){

        //通过es分组查询,查询主题列表:themeId themeName count

        //es查询语句的构建类
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //分组列对象集合
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.field(idField);
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        nameSource.field(nameField);
        sources.add(idSource);
        sources.add(nameSource);
        //构建分组语法
        CompositeAggregationBuilder aggBuilder = new CompositeAggregationBuilder(groupName,sources);
        builder.addAggregation(aggBuilder);
        //分页
        builder.withPageable(PageRequest.of(0,1));
        //明确查询那个所有那个类型
        builder.withIndices(StrategyTemplate.INDEX_NAME);
        builder.withTypes(StrategyTemplate.TYPE_NAME);
        AggregatedPage<StrategyTemplate> search = (AggregatedPage)repository.search(builder.build());

        //解析结果
        List<StatisVO> list = new ArrayList<>();
        InternalComposite group = (InternalComposite)search.getAggregation(groupName);
        for (CompositeAggregation.Bucket bucket : group.getBuckets()) {
            Long id = Long.parseLong(bucket.getKey().get("id").toString());
            String name = bucket.getKey().get("name").toString();
            Long count = bucket.getDocCount();

            StatisVO vo = new StatisVO();
            vo.setId(id);
            vo.setCount(count);
            vo.setName(name);
            list.add(vo);
        }

        //优化1 排序
        Collections.sort(list, new Comparator<StatisVO>() {
            @Override
            public int compare(StatisVO o1, StatisVO o2) {
                Long ret = o2.getCount() - o1.getCount();
                return ret.intValue();
            }
        });

        return list;
    }

    @Override
    public List<StatisVO> queryConditionChina() {
        return this.getStatsVoList
                ("provinceId","provinceName","provinceGroup");
    }

    @Override
    public List<StatisVO> queryConditionAbroads() {
        return this.getStatsVoList
                ("countryId","countryName","countryGroup");
    }

    @Override
    public List<StatisVO> queryConditionThemes() {
        return this.getStatsVoList
                ("themeId","themeName","themeGroup");
    }

    private List<StatisVO> getDestByThemeId(Long themeId){
        List<StatisVO> vos = new ArrayList<>();
        List<StrategyTemplate> templates = repository.findByThemeId(themeId);
        //优化3目的地去重
        List<String> list = new ArrayList<>();
        for (StrategyTemplate template : templates) {
            if (!list.contains(template.getDestName())) {
                StrategyDetail detail = strategyDetailService.get(template.getId());
                StatisVO vo = new StatisVO();
                vo.setId(detail.getDest().getId());
                vo.setName(template.getDestName());
                vos.add(vo);
            }
        }
        return vos;
    }

    @Override
    public void save(StrategyTemplate strategyTemplate) {
        repository.save(strategyTemplate);
    }

    @Override
    public Page query(StrategySearchQuery qo) {
        TermQueryBuilder query = null;
        //分页参数对象
        PageRequest of = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.Direction.DESC, qo.getOrderBy());

        if(qo.getType()==StrategySearchQuery.CONDITION_TYPE_COUNTRY){
            //国家
            query=QueryBuilders.termQuery("countryId",qo.getTypeValue());
        }else if(qo.getType()==StrategySearchQuery.CONDITION_TYPE_PROVINCE){
            //省份
            query=QueryBuilders.termQuery("provinceId",qo.getTypeValue());
        }else if(qo.getType()==StrategySearchQuery.CONDITION_TYPE_THEME){
            //主题
            query=QueryBuilders.termQuery("themeId",qo.getTypeValue());
        }
        if(query==null){
            return repository.findAll(of);
        }else{
            return repository.search(query,of);
        }
    }

    @Override
    public List<StrategyTemplate> findByDestName(String destName) {
        return repository.findByDestName(destName);
    }
}
